package service

import (
	"context"
	"errors"
	"fmt"
	"mime/multipart"
	"time"

	"github.com/example/video_backend/internal/model"
	"github.com/example/video_backend/internal/repository"
)

// VideoService 视频服务接口
type VideoService interface {
	UploadVideo(ctx context.Context, video *model.Video, videoFile *multipart.FileHeader, coverFile *multipart.FileHeader) error
	GetVideoInfo(ctx context.Context, videoID uint) (*model.Video, error)
	UpdateVideo(ctx context.Context, video *model.Video) error
	DeleteVideo(ctx context.Context, videoID uint) error
	ListVideos(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*model.Video, int64, error)
	WatchVideo(ctx context.Context, videoID uint) error
	LikeVideo(ctx context.Context, userID, videoID uint) error
	UnlikeVideo(ctx context.Context, userID, videoID uint) error
	IsVideoLiked(ctx context.Context, userID, videoID uint) (bool, error)
	CollectVideo(ctx context.Context, userID, videoID uint) error
	UncollectVideo(ctx context.Context, userID, videoID uint) error
	IsVideoCollected(ctx context.Context, userID, videoID uint) (bool, error)
}

// videoService 实现VideoService接口
type videoService struct {
	videoRepo      repository.VideoRepository
	likeRepo       repository.LikeRepository
	collectionRepo repository.CollectionRepository
}

// NewVideoService 创建视频服务实例
func NewVideoService(
	videoRepo repository.VideoRepository,
	likeRepo repository.LikeRepository,
	collectionRepo repository.CollectionRepository,
) VideoService {
	return &videoService{
		videoRepo:      videoRepo,
		likeRepo:       likeRepo,
		collectionRepo: collectionRepo,
	}
}

// UploadVideo 上传视频
func (s *videoService) UploadVideo(ctx context.Context, video *model.Video, videoFile *multipart.FileHeader, coverFile *multipart.FileHeader) error {
	// 设置创建和更新时间
	video.CreatedAt = time.Now()
	video.UpdatedAt = time.Now()
	//
	//// 上传视频到本地文件系统
	//videoPath := "/mnt/tf/video/" + videoFile.Filename
	//if err := ctx.(*gin.Context).SaveUploadedFile(videoFile, videoPath); err != nil {
	//	return fmt.Errorf("上传视频文件失败: %w", err)
	//}
	//video.VideoURL = "/videos/" + videoFile.Filename
	//
	//// 上传封面图片到本地文件系统
	//if coverFile != nil {
	//	coverPath := "/mnt/tf/video/" + coverFile.Filename
	//	if err := ctx.(*gin.Context).SaveUploadedFile(coverFile, coverPath); err != nil {
	//		return fmt.Errorf("上传封面图片失败: %w", err)
	//	}
	//	video.CoverURL = "/covers/" + coverFile.Filename
	//}

	// 创建视频记录
	if err := s.videoRepo.Create(ctx, video); err != nil {
		return fmt.Errorf("创建视频记录失败: %w", err)
	}

	return nil
}

// GetVideoInfo 获取视频信息
func (s *videoService) GetVideoInfo(ctx context.Context, videoID uint) (*model.Video, error) {
	return s.videoRepo.GetByID(ctx, videoID)
}

// UpdateVideo 更新视频信息
func (s *videoService) UpdateVideo(ctx context.Context, video *model.Video) error {
	// 查找视频
	existingVideo, err := s.videoRepo.GetByID(ctx, video.ID)
	if err != nil {
		return err
	}
	if existingVideo == nil {
		return errors.New("视频不存在")
	}

	// 更新视频信息
	existingVideo.Title = video.Title
	existingVideo.Description = video.Description
	existingVideo.CoverURL = video.CoverURL
	existingVideo.VideoURL = video.VideoURL
	existingVideo.Duration = video.Duration
	existingVideo.IsPublic = video.IsPublic
	existingVideo.CategoryID = video.CategoryID
	existingVideo.UpdatedAt = time.Now()

	return s.videoRepo.Update(ctx, existingVideo)
}

// DeleteVideo 删除视频
func (s *videoService) DeleteVideo(ctx context.Context, videoID uint) error {
	return s.videoRepo.Delete(ctx, videoID)
}

// ListVideos 获取视频列表
func (s *videoService) ListVideos(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*model.Video, int64, error) {
	return s.videoRepo.List(ctx, page, pageSize, filters)
}

// WatchVideo 观看视频（增加观看次数）
func (s *videoService) WatchVideo(ctx context.Context, videoID uint) error {
	return s.videoRepo.IncreaseViews(ctx, videoID)
}

// LikeVideo 点赞视频
func (s *videoService) LikeVideo(ctx context.Context, userID, videoID uint) error {
	// 检查是否已经点赞
	isLiked, err := s.likeRepo.IsLiked(ctx, userID, videoID)
	if err != nil {
		return err
	}
	if isLiked {
		return errors.New("已经点赞过了")
	}

	// 创建点赞记录
	like := &model.Like{
		UserID:  userID,
		VideoID: videoID,
	}
	if err := s.likeRepo.Create(ctx, like); err != nil {
		return fmt.Errorf("创建点赞记录失败: %w", err)
	}

	// 增加视频点赞数
	if err := s.videoRepo.IncreaseLikesCount(ctx, videoID); err != nil {
		return fmt.Errorf("更新视频点赞数失败: %w", err)
	}

	return nil
}

// UnlikeVideo 取消点赞
func (s *videoService) UnlikeVideo(ctx context.Context, userID, videoID uint) error {
	// 检查是否已经点赞
	isLiked, err := s.likeRepo.IsLiked(ctx, userID, videoID)
	if err != nil {
		return err
	}
	if !isLiked {
		return errors.New("尚未点赞")
	}

	// 删除点赞记录
	if err := s.likeRepo.Delete(ctx, userID, videoID); err != nil {
		return fmt.Errorf("删除点赞记录失败: %w", err)
	}

	// 减少视频点赞数
	if err := s.videoRepo.DecreaseLikesCount(ctx, videoID); err != nil {
		return fmt.Errorf("更新视频点赞数失败: %w", err)
	}

	return nil
}

// IsVideoLiked 检查用户是否已点赞视频
func (s *videoService) IsVideoLiked(ctx context.Context, userID, videoID uint) (bool, error) {
	return s.likeRepo.IsLiked(ctx, userID, videoID)
}

// CollectVideo 收藏视频
func (s *videoService) CollectVideo(ctx context.Context, userID, videoID uint) error {
	// 检查是否已经收藏
	isCollected, err := s.collectionRepo.IsCollected(ctx, userID, videoID)
	if err != nil {
		return err
	}
	if isCollected {
		return errors.New("已经收藏过了")
	}

	// 创建收藏记录
	collection := &model.Collection{
		UserID:  userID,
		VideoID: videoID,
	}
	if err := s.collectionRepo.Create(ctx, collection); err != nil {
		return fmt.Errorf("创建收藏记录失败: %w", err)
	}

	return nil
}

// UncollectVideo 取消收藏
func (s *videoService) UncollectVideo(ctx context.Context, userID, videoID uint) error {
	// 检查是否已经收藏
	isCollected, err := s.collectionRepo.IsCollected(ctx, userID, videoID)
	if err != nil {
		return err
	}
	if !isCollected {
		return errors.New("尚未收藏")
	}

	// 删除收藏记录
	if err := s.collectionRepo.Delete(ctx, userID, videoID); err != nil {
		return fmt.Errorf("删除收藏记录失败: %w", err)
	}

	return nil
}

// IsVideoCollected 检查用户是否已收藏视频
func (s *videoService) IsVideoCollected(ctx context.Context, userID, videoID uint) (bool, error) {
	return s.collectionRepo.IsCollected(ctx, userID, videoID)
}
